package main

import (
	"encoding/json"
	"fmt"
)

/**
JSON介绍
	JSON（JavaScript Object Notation，JavaScript对象表示法）是一种轻量级的数据交换格式，因简单、可读性强被广泛使用。
	Go的标准包encoding/json对JSON的支持
*/
func main() {

	/*
		一. json.Marshal()函数之map转json。返回的JSON字符串是没有空白字符和缩进的，最常用但是不好阅读
			TIPS:
				· JSON对象只支持string作为key，所以要编码一个map，必须是map[string]T这种类型（T是Go语言中的任意类型）；
				· channel、complex和function是不能被编码成JSON的；
				· 指针在编码的时候会输出指针指向的内容，而空指针会输出null；
	*/
	m := make(map[string]interface{})
	m["code"] = "000000"
	m["message"] = "success"
	m["data"] = 1233
	if marshal, err := json.Marshal(m); err == nil {
		fmt.Println(marshal)
		fmt.Println("map转json: \n", string(marshal))
	}

	/*
		二. json.MarshalIndent()函数之map转json
			TIPS：该函数有两个参数表示每一行的前缀和缩进方式。生成便于阅读的格式
	*/
	m2 := map[string][]interface{}{
		"code":    {"000000"},
		"message": {"success"},
		"data":    {"23232", 32323},
	}
	if indent, err := json.MarshalIndent(m2, " ", "  "); err == nil {
		fmt.Println("map转json: \n", string(indent))
	}

	/*
		三. 结构体转JSON
			TIPS：json包是通过【反射机制】来实现编解码的，因此结构体必须导出所转换的字段，没有导出的字段（即非大写开头属性）不会被json包解析
	*/
	info := ResponseInfo{
		Code:    "000000",
		DAta:    "ResponseInfo",
		Message: "responseInfoSuccess",
		id:      0,
	}
	if marshal, err := json.Marshal(info); err == nil {
		fmt.Println("结构体转json: \n", string(marshal))
	}
	if marshal, err := json.MarshalIndent(info, " ", "  "); err == nil {
		fmt.Println("结构体转json: \n", string(marshal))
	}

	infos := []ResponseInfo{
		{"111111", "", "fail", 1},
		{"000000", "434", "success", 2},
	}
	if marshal, err := json.Marshal(infos); err == nil {
		fmt.Println("结构体数组转json: \n", string(marshal))
	}
	if marshal, err := json.MarshalIndent(infos, " ", "  "); err == nil {
		fmt.Println("结构体数组转json: \n", string(marshal))
	}

	/*
		三. 结构体字段标签。json包在解析【结构体】时，如果遇到key为JSON的字段标签，则会按照一定规则解析该标签
	*/

	user := User{
		Card: Card{"5123468343434657", "上海嘉定"},
		Name: "结构体字段按标签展示",
		Age:  20,
		Sex:  1,
		addr: "上海",
	}
	user.ResponseInfo = ResponseInfo{
		Code:    "000000",
		DAta:    "rerer",
		Message: "recxgrg ",
		id:      10,
	}
	if marshal, err := json.Marshal(user); err == nil {
		fmt.Println(string(marshal))
	}
}

/*
首字母小写不会被json 解析
*/
type ResponseInfo struct {
	Code    string // 导出字段会被json 解析（首字母大写）
	DAta    string // 只要首字母大写都会被作为导出字段会被json 解析
	Message string
	id      int // 未导出字段不会被json 解析（首字母小写）
}

type Card struct {
	Number string `json:"身份证号"`
	place  string
}

/*
结构体字段标签
*/
type User struct {
	Card        // json包在解析匿名字段时，会将匿名字段的字段当成该结构体的字段处理
	Name string `json:"_name"`
	Age  int    `json:"_age"`
	Sex  int    `json:"_sex"`
	addr string `json:"_addr"` // 未导出字段不会被json 解析（首字母小写）

	ResponseInfo ResponseInfo `json:"response"` // json包在解析嵌套结构体时,嵌套结构体的字段不会被当成该结构体的字段处理
}
